define(function(require) {
    'use strict';
    var Backbone = require('backbone'),
        Utils = require('core/utils'),
        Config = require('models/config'),
        $ = require('jquery'),
        _ = require('underscore'),
        SHOWCASE_CONFIG = require('components/showcase/2.0.0/config'),
        Storage = require('components/showcase/2.0.0/base/storage');

    return Backbone.Collection.extend({
        // 需要子类重写该属性
        url: '',
        // 需要子类重写该属性
        storageName: '',

        model: function(attrs, options) {
            if (!SHOWCASE_CONFIG.models) {
                return new Config(attrs, options);
            }
            if (!(attrs.type in SHOWCASE_CONFIG.models)) {
                if (attrs.type === 'config') {
                    return new Config(attrs, options);
                }
                throw 'type error';
            }

            return SHOWCASE_CONFIG.models[attrs.type].initialize(attrs, options);
        },

        initialize: function(models, options) {
            this.options = options || {};
            if(!_.isUndefined(this.options.id)) {
                this.id = this.options.id;
            }

            this.storage = new Storage(this.storageName, options);

            this.changed = false;

            // 数据几何是否改变
            this.listenTo(this, 'add remove sort reset', this._changed);
            this.listenTo(this, 'sync', this._unchanged);
        },

        _changed: function(){
            this.changed = true;
        },

        _unchanged: function() {
            this.changed = false;
        },

        validate: function() {
        	var ret = true;
			this.every(function(model) {
                var result = model.checkValid();
                if(result) {
                    model.trigger('valid:error');
                }
                ret = ret&result!=undefined;
            });
			return ret==1?{}:undefined;
        },

        parse: function(models) {
            // 剔除脏数据
            var filtered = _.reject(models, function(model) {
                if (SHOWCASE_CONFIG.models) {
                    return _.isArray(model) || _.isEmpty(model) || (!(model.type in SHOWCASE_CONFIG.models) && model.type !== 'config');
                } else {
                    return _.isArray(model) || _.isEmpty(model);
                }
            });

            if (_.isEmpty(filtered) && !this.noConfig) {
                filtered.push(_.clone(_.result(Config.prototype, 'defaults')));
                if (_.isFunction(this.parseEmptyData)) {
                    return this.parseEmptyData(filtered);
                }
            }

            if (_.isFunction(this.onParse)) {
                return this.onParse(filtered);
            }

            return filtered;
        },

        localSync: function() {
            if(!this.length) {
                this.clearLocalData();
                return;
            }
            if(this.hasChanged()){
                this.storage.setItem(this.toJSON());
            }
        },

        localFetch: function() {
            return this.storage.getItem();
        },

        clearLocalData: function() {
            this.storage.removeItem();
        },

        fetch: function(options) {
            var url = this.url + '?id=' + this.id;
            return Utils.ajax(url, options)
                .done(_.bind(this._fetchDone, this))
                .fail(_.bind(this.error, this));
        },

        _fetchDone: function(data) {
            _.extend(this, _.pick(data, 'is_display', 'alias', 'title', 'id', 'num', 'start_sold_item', 'valid', 'out_id'));

            var is_default = data.is_default;
            if (is_default && data.data.length > 0 && data.data[0].type == 'config') {
                data.data[0].is_default = is_default;
            }

            this.set(data.data, {parse: true, silent: true});
            this.trigger('sync');
        },

        sync: function(options) {
            options = options || {};

            // 校验
            if(this.validate()) {
                $('.form-actions .btn').button('reset');
                return $.Deferred();
            }

            this.beforeSync();

            var
                id = options.id || this.id,
                url = options.url || this.url,
                method = options.method || (id ? 'PUT' : 'POST'),
                _data = _.extend({
                    data: JSON.stringify(this),
                    is_display: 0
                }, _.pick(this, 'is_display', 'alias', 'title', 'id', 'num', 'start_sold_item', 'valid', 'out_id'), options);


            var params = {
                url: url,
                method: method,
                data: this.handleData(_data)
            };

            return Utils.ajax(params)
                .done(_.bind(this._syncDone, this))
                .fail(_.bind(this.error, this));
        },

        handleData: function(data){
            return data;
        },

        beforeSync: function() {
            var configModel = this.at(0);
            if(configModel.get('type') === 'config') {
                if(this.includeFullscreenModel()) {
                    configModel.set('has_fullscreen_component', '1');
                } else {
                    configModel.unset('has_fullscreen_component');
                }
            }
        },

        _syncDone: function(data) {
            if(_.isUndefined(this.id)) {
                this.id = data.id;
            }
            this.clearLocalData();
        },

        error: function(msg) {
            Utils.errorNotify(msg);
        },


        hasChanged: function(){
            if(this.changed) return true;

            return this.any(function(model){
                return model.hasChanged();
            });
        },

        includeConfigModel: function() {
            var first = this.first();
            return !!first && first.attributes.type === 'config';
        },

        includeFullscreenModel: function() {
            return this.any(function(model){
                return !!model.get('is_fullscreen_component');
            });
        }
    });
});
